package org.bit.practice03;

/**
 * 自己实现一个阻塞队列
 */

public class MyBlockingQueue {
    // 定义一个数组来存放数据，具体的容量由构造方法中的参数决定
    private Integer[] elementDate;
    // 定义头尾下标
    private volatile int head = 0;
    private volatile int tail = 0;
    // 定义数组中元素的个数
    private volatile int size = 0;

    // 构造方法
    public MyBlockingQueue(int capacity) {
        if (capacity <= 0) {
            throw new RuntimeException("队列容量必须大于0.");
        }
        elementDate = new Integer[capacity];
    }

    // 插入数据的方法
    public void put(Integer value) throws InterruptedException {
        synchronized (this) {
            // 判断队列是否已满
            while (size >= elementDate.length) {
                // 阻塞队列在队列满的时候就应该阻塞等待
                // 等待
                this.wait();
            }
            // 插入数据的过程
            // 在队列尾部插入元素
            elementDate[tail] = value;
            // 移动队尾下表标
            tail++;
            // 处理队尾下标
            if (tail >= elementDate.length) {
                tail = 0;// 回到数据头
            }
            // 修改 size 值
            size++;
            // 唤醒阻塞等待的线程
            this.notifyAll();
        }
    }

    // 获取数据的方法
    public synchronized Integer take () throws InterruptedException {
        // 判断队列是否为空
        while (size == 0) {
            this.wait();
        }
        // 出队的过程
        // 获取要出队的元素
        Integer value = elementDate[head];
        // 移动队头下标
        head++;
        // 处理队头下标
        if (head >= elementDate.length) {
            head = 0;// 回到数据头
        }
        // 处理数组中元素的个数
        size--;
        // 唤醒阻塞等待的线程
        synchronized (this) {
            this.notifyAll();
        }
        return value;
    }
}






















